All files / middleware addonCheck.js

0% Statements 0/34
0% Branches 0/13
0% Functions 0/5
0% Lines 0/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125                                                                                                                                                                                                                                                         
/**
 * Addon Check Middleware
 * Verifies if a system addon is installed and active before allowing access
 * 
 * @module middleware/addonCheck
 */
 
const { pool } = require('../config/database');
const { logger } = require('../config/logger');
 
/**
 * Cache for addon status to avoid repeated database queries
 * Cache expires after 60 seconds
 */
const addonCache = new Map();
const CACHE_TTL = 60000; // 60 seconds
 
/**
 * Check if a system addon is installed and active
 * @param {string} addonSlug - The slug of the addon to check
 * @returns {Promise<{installed: boolean, active: boolean}>}
 */
async function checkAddonStatus(addonSlug) {
  const cacheKey = `addon_${addonSlug}`;
  const cached = addonCache.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.status;
  }
 
  try {
    const [addons] = await pool.execute(
      'SELECT id, active FROM system_addons WHERE slug = ?',
      [addonSlug]
    );
 
    const status = {
      installed: addons.length > 0,
      active: addons.length > 0 && (addons[0].active === 1 || addons[0].active === true)
    };
 
    addonCache.set(cacheKey, { status, timestamp: Date.now() });
    return status;
  } catch (error) {
    logger.error('Error checking addon status', { addonSlug, error: error.message });
    // If table doesn't exist, addon system is not set up
    return { installed: false, active: false };
  }
}
 
/**
 * Clear addon cache (useful when addon status changes)
 * @param {string} [addonSlug] - Optional specific addon to clear, or all if not provided
 */
function clearAddonCache(addonSlug) {
  if (addonSlug) {
    addonCache.delete(`addon_${addonSlug}`);
  } else {
    addonCache.clear();
  }
}
 
/**
 * Middleware factory to require a specific addon to be active
 * @param {string} addonSlug - The slug of the required addon
 * @returns {Function} Express middleware
 */
function requireAddon(addonSlug) {
  return async (req, res, next) => {
    try {
      const status = await checkAddonStatus(addonSlug);
 
      if (!status.installed) {
        return res.status(403).json({
          success: false,
          message: `The ${addonSlug} addon is not installed. Please contact your administrator.`,
          error: 'ADDON_NOT_INSTALLED',
          addon: addonSlug
        });
      }
 
      if (!status.active) {
        return res.status(403).json({
          success: false,
          message: `The ${addonSlug} addon is not active. Please contact your administrator.`,
          error: 'ADDON_NOT_ACTIVE',
          addon: addonSlug
        });
      }
 
      // Addon is installed and active, proceed
      next();
    } catch (error) {
      logger.error('Error in requireAddon middleware', { addonSlug, error: error.message });
      return res.status(500).json({
        success: false,
        message: 'Error checking addon status'
      });
    }
  };
}
 
/**
 * Get all active addons
 * @returns {Promise<Array>} List of active addons
 */
async function getActiveAddons() {
  try {
    const [addons] = await pool.execute(
      'SELECT slug, name, icon, config FROM system_addons WHERE active = 1'
    );
    return addons;
  } catch (error) {
    logger.error('Error getting active addons', { error: error.message });
    return [];
  }
}
 
module.exports = {
  checkAddonStatus,
  clearAddonCache,
  requireAddon,
  getActiveAddons
};